package gameoflife;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import org.junit.Test;

public class GameOfLifeTest {

	@Test
	public void allCellsAreDeathForgame() throws Exception {
		GameOfLife game = new GameOfLife(5, 5);
		for (int x = 0; x < 5; x++)
			for (int y = 0; y < 5; y++)
				assertThat(game.isLive(x, y), is(false));
	}

	@Test
	public void liveCellWithoutLiveNeighboursDies() throws Exception {
		GameOfLife game = new GameOfLife(1, 1);
		game.setLive(0, 0);
		game.tick();
		assertThat(game.isLive(0, 0), is(false));
	}

	@Test
	public void liveCellWithOneLiveNeighbourDies() throws Exception {
		GameOfLife game = new GameOfLife(2, 1);
		game.setLive(0, 0);
		game.setLive(1, 0);
		game.tick();
		assertThat(game.isLive(0, 0), is(false));
		assertThat(game.isLive(1, 0), is(false));
	}

	@Test
	public void liveCellWithTwoLiveNeighoursLives() throws Exception {
		GameOfLife game = new GameOfLife(2, 2);
		game.setLive(0, 0);
		game.setLive(1, 0);
		game.setLive(0, 1);
		game.tick();
		assertThat(game.isLive(0, 0), is(true));
		assertThat(game.isLive(1, 0), is(true));
		assertThat(game.isLive(0, 1), is(true));
	}

	@Test
	public void liveCellWithThreeLiveNeighboursLives() throws Exception {
		GameOfLife game = new GameOfLife(2, 2);
		game.setLive(0, 0);
		game.setLive(1, 0);
		game.setLive(0, 1);
		game.setLive(1, 1);
		game.tick();
		assertThat(game.isLive(0, 0), is(true));
		assertThat(game.isLive(1, 0), is(true));
		assertThat(game.isLive(0, 1), is(true));
		assertThat(game.isLive(1, 1), is(true));
	}

	@Test
	public void liveCellWithFourNeighboursDies() throws Exception {
		GameOfLife game = new GameOfLife(3, 3);
		game.setLive(1, 1);
		game.setLive(1, 2);
		game.setLive(1, 0);
		game.setLive(0, 1);
		game.setLive(2, 1);
		game.tick();
		assertThat(game.isLive(1, 1), is(false));
		assertThat(game.isLive(1, 2), is(true));
		assertThat(game.isLive(1, 0), is(true));
		assertThat(game.isLive(0, 1), is(true));
		assertThat(game.isLive(2, 1), is(true));
	}

	@Test
	public void blockAlwaysLives() throws Exception {
		GameOfLife game = new GameOfLife(3, 3);
		game.setLive(0, 0);
		game.setLive(1, 0);
		game.setLive(0, 1);
		game.setLive(1, 1);
		game.tick();
		assertBlockLives(game);
		game.tick();
		assertBlockLives(game);
		game.tick();
		assertBlockLives(game);
	}

	private void assertBlockLives(GameOfLife game) {
		assertThat(game.isLive(0, 0), is(true));
		assertThat(game.isLive(1, 0), is(true));
		assertThat(game.isLive(1, 0), is(true));
		assertThat(game.isLive(1, 1), is(true));
	}

	@Test
	public void newCellBornsWhenItHasForLiveNeighbours() throws Exception {
		GameOfLife game = new GameOfLife(3, 3);
		game.setLive(0, 1);
		game.setLive(0, 2);
		game.setLive(1, 2);
		game.tick();
		assertThat(game.isLive(1, 1), is(true));
	}

	@Test
	public void shouldBeBlockInNextGeneration() throws Exception {
		GameOfLife game = new GameOfLife(3, 3);
		game.setLive(0, 1);
		game.setLive(0, 2);
		game.setLive(1, 2);
		game.tick();
		assertThat(game.isLive(1, 1), is(true));
		assertThat(game.isLive(0, 1), is(true));
		assertThat(game.isLive(0, 2), is(true));
		assertThat(game.isLive(1, 2), is(true));
	}
}
